import { Component, OnInit } from '@angular/core'
import { FormBuilder, Validators, FormGroup, FormControl } from '@angular/forms'
import { NzMessageService } from 'ng-zorro-antd'

import { TerminalStoreService } from '../terminal-store.service'
import { TerminalNewBaseClass } from '../baseClass'
import { makeAllControlDirty, generateOptions } from 'app/utils/helpers'
import { alphanumericReg, termCodeLength, onlyNumberReg } from 'app/utils/contraints'
import { TermCodeConflictAsyncValidator } from 'app/utils/form-control.validator'
import { BusinessService } from '@shared/services/business.service'
import { I18NService } from '@core'
import { Terminal, TerminalNewRequest, ETermVendar } from '@shared/interfaces/terminal'
import { IOption } from '@shared/interfaces/common'
import { PublicService } from '@shared/services/public.service'

@Component({
  selector: 'app-terminal-new-base',
  templateUrl: './base.component.html',
  styleUrls: ['../../../../shared/styles/new-page-form.less'],
})
export class TerminalNewBaseComponent extends TerminalNewBaseClass implements OnInit {
  manualForms: FormGroup[] = []
  autoForm: FormGroup
  modeForm: FormGroup

  mode = 1

  errorTips = {}

  terminalModes = [
    { label: this.trans('BIZ.TERMINAL.ONBOARDING_MODE.AUTO'), value: 1 },
    { label: this.trans('BIZ.TERMINAL.ONBOARDING_MODE.MANUAL'), value: 2 },
  ]

  termBrandOptions: IOption[]

  constructor(
    private bizService: BusinessService,
    private i18n: I18NService,
    public msg: NzMessageService,
    public fb: FormBuilder,
    public terminalStore: TerminalStoreService,
    private publicService: PublicService,
  ) {
    super(fb, terminalStore)
  }

  ngOnInit() {
    this.initErrorTips()
    this.termBrandOptions = this.genTermBrandOptions()
    this.terminalStore.value$.subscribe(terminal => (this.terminal = terminal))
    // 这里拿取mode 如果是之前terminal有存下就直接拿
    this.mode = this.terminal.mode ? this.terminal.mode : this.mode
    this.generateForm(this.terminal)
  }

  initErrorTips(): void {
    this.errorTips = {
      termCode: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('GENERAL.TERMINAL.CODE') }),
        pattern: this.trans('VALIDATION.PATTERN.ALPHANUMERIC_ONLY'),
        maxlength: this.trans('VALIDATION.MAX_LENGTH', { length: 8 }),
        termCodeConflicting: this.trans('VALIDATION.CODE_EXISTS', { name: this.trans('GENERAL.TERMINAL.CODE') }),
        isNumTaken: this.trans('VALIDATION.CODE_EXISTS', { name: this.trans('GENERAL.TERMINAL.CODE') }),
      },
      count: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('BIZ.TERMINAL.QUANTITY') }),
        min: this.trans('VALIDATION.MIN_VALUE', { value: 1 }),
        max: this.trans('VALIDATION.MAX_VALUE', { value: 200 }),
        pattern: this.trans('VALIDATION.PATTERN.INTEGER_ONLY'),
      },
    }
  }

  genTermBrandOptions(): IOption[] {
    return this.publicService.genOptions(ETermVendar)
  }

  setMode(mode) {
    this.mode = mode
    this.generateForm(this.terminal)
  }

  pushDataToStore(): void {
    const tmp = this.terminal
    Object.assign(tmp, this.modeForm.value)
    if (this.mode === 1) {
      Object.assign(tmp, this.autoForm.value)
      if (typeof this.autoForm.value.count === 'string') {
        tmp.count = parseInt(this.autoForm.value.count, 10)
      }
      tmp.termCodes = []
      this.manualForms.forEach(form => form.reset())
    } else {
      tmp.termCodes = this.manualForms.map(form => form.value.termCode)
      this.autoForm.reset()
      delete tmp.count
    }
    this.terminalStore.updateValue(tmp)
  }

  addTerminal() {
    this.generateManualForm('')
  }

  minusTerminal(index) {
    this.removeTerminal(index)
  }

  checkValid() {
    if (!this.isValid()) {
      this.checkValidFail()
      return false
    } else {
      this.checkValidSuccess()
      return true
    }
  }

  computeTerminalTitle(idx: number): string {
    return `${this.trans('GENERAL.BIZ_LEVEL.TERMINAL')} ${idx + 1}`
  }

  trans(key: string, params?: Object): string {
    return this.i18n.fanyi(key, params)
  }

  private isValid() {
    let valid = true
    if (this.mode === 1) {
      return this.autoForm.valid
    } else {
      this.manualForms.forEach(form => {
        if (!form.valid) {
          valid = false
        }
      })
      return valid
    }
  }

  private checkValidFail() {
    this.msg.error(this.trans('GENERAL.NOTIFICATION.VALIDATION_FAIL'))
    // this.makeAllControlDirty(this.commonForm)
    if (this.mode === 1) {
      makeAllControlDirty(this.autoForm)
    } else {
      this.manualForms.forEach(form => {
        makeAllControlDirty(form)
      })
    }
  }

  private checkValidSuccess() {
    this.msg.success(this.trans('GENERAL.NOTIFICATION.VALIDATION_SUCCESS'))
    this.pushDataToStore()
  }

  private generateManualForm(termCode: string) {
    this.manualForms.push(
      this.fb.group({
        termCode: new FormControl(termCode, {
          validators: [Validators.required, Validators.pattern(alphanumericReg), Validators.maxLength(termCodeLength)],
          asyncValidators: [
            TermCodeConflictAsyncValidator(this.bizService, this.manualForms, 'termCode', this.terminal.intStoreCode),
          ],
        }),
      }),
    )
  }

  private generateForm(terminal: TerminalNewRequest) {
    const { termVendar }  = terminal
    this.modeForm = this.fb.group({
      mode: [this.mode, [Validators.required]],
      termVendar: [termVendar, []],
    })
    if (this.mode === 2) {
      /* 從新創造新的manualForms 不然的話儅mode換value的時候manualForms會一直加 */
      this.manualForms = []
      if (!terminal.termCodes || terminal.termCodes.length === 0) {
        this.generateManualForm('')
        return
      }

      const termCodes = terminal.termCodes
      termCodes.forEach(this.generateManualForm.bind(this))
    } else {
      this.autoForm = this.fb.group({
        count: [
          terminal.count,
          [Validators.required, Validators.min(1), Validators.max(200), Validators.pattern(onlyNumberReg)],
        ],
      })
    }
  }

  private removeTerminal(index) {
    if (this.manualForms.length <= 1) {
      return
    }
    this.manualForms.forEach((form, i) => {
      if (i === index) {
        this.manualForms.splice(i, 1)
      }
    })
  }
}
